<?php

declare(strict_types=1);

namespace app\admin\controller;

use app\admin\constants\AdminConstants;
use app\admin\library\Auth;
use app\admin\model\Admin;
use Throwable;
use ba\ClickCaptcha;
use think\facade\Config;
use think\facade\Validate;
use app\common\facade\Token;
use app\admin\model\AdminLog;
use app\common\controller\Backend;
use think\facade\Cache;

class Index extends Backend
{
    protected array $noNeedLogin      = ['logout', 'login', 'migration'];
    protected array $noNeedPermission = ['index', 'migration'];

    /**
     * 后台初始化请求
     * @return void
     * @throws Throwable
     */
    public function index(): void
    {

        $adminInfo          = $this->auth->getInfo();
        $adminInfo['super'] = $this->auth->isSuperAdmin();
        // $adminInfo['adminStores'] = [['id' => 1, 'name' => '第1家门店第1家门店第1家门店第1家门店第1家门店第1家门店'], ['id' => 2, 'name' => 'test家门店'], ['id' => 3, 'name' => '第三家门店'], ['id' => 4, 'name' => '第4家门店'], ['id' => 5, 'name' => '第5家门店']];
        Cache::store('redis')->delete(AdminConstants::ADMIN_STORES_CACHE_KEY . $this->auth->id); //先删除缓存，后面重新设置
        $adminStores = Admin::getLoginAdminStores(); //登陆用户关联的门店
        // $adminInfo['adminStores'] = array_merge([['id' => 0, 'name' => '全部门店']], $adminStores['adminStores'] ?? []);
        $adminInfo['adminStores'] = array_merge($adminStores['adminStores'] ?? []);


        unset($adminInfo['token'], $adminInfo['refresh_token']);

        $menus = $this->auth->getMenus();
        if (!$menus) {
            $this->error(__('No background menu, please contact super administrator!'));
        }
        $this->success('', [
            'adminInfo'   => $adminInfo,
            'menus'       => $menus,
            'siteConfig'  => [
                'siteName'     => get_sys_config('site_name'),
                'version'      => get_sys_config('version'),
                'apiUrl'       => Config::get('buildadmin.api_url'),
                'upload'       => keys_to_camel_case(get_upload_config(), ['max_size', 'save_name', 'allowed_suffixes', 'allowed_mime_types']),
                'cdnUrl'       => full_url(),
                'cdnUrlParams' => Config::get('buildadmin.cdn_url_params'),
            ],
            'terminal'   => [
                'phpDevelopmentServer' => str_contains($_SERVER['SERVER_SOFTWARE'], 'Development Server'),
                'npmPackageManager'    => Config::get('terminal.npm_package_manager'),
            ]
        ]);
    }

    /**
     * 管理员登录
     * @return void
     * @throws Throwable
     */
    public function login(): void
    {
        // 检查登录态
        if ($this->auth->isLogin()) {
            $this->success(__('You have already logged in. There is no need to log in again~'), [
                'type' => $this->auth::LOGGED_IN
            ], $this->auth::LOGIN_RESPONSE_CODE);
        }

        $captchaSwitch = Config::get('buildadmin.admin_login_captcha');

        // 检查提交
        if ($this->request->isPost()) {
            $username = $this->request->post('username');
            $password = $this->request->post('password');
            $keep     = $this->request->post('keep');

            $rule = [
                'username|' . __('Username') => 'require|length:3,30',
                'password|' . __('Password') => 'require|regex:^(?!.*[&<>"\'\n\r]).{6,32}$',
            ];
            $data = [
                'username' => $username,
                'password' => $password,
            ];
            if ($captchaSwitch) {
                $rule['captchaId|' . __('CaptchaId')] = 'require';
                $rule['captchaInfo|' . __('Captcha')] = 'require';

                $data['captchaId']   = $this->request->post('captchaId');
                $data['captchaInfo'] = $this->request->post('captchaInfo');
            }
            $validate = Validate::rule($rule);
            if (!$validate->check($data)) {
                $this->error($validate->getError());
            }

            if ($captchaSwitch) {
                $captchaObj = new ClickCaptcha();
                if (!$captchaObj->check($data['captchaId'], $data['captchaInfo'])) {
                    $this->error(__('Captcha error'));
                }
            }

            AdminLog::instance()->setTitle(__('Login'));

            $res = $this->auth->login($username, $password, (bool)$keep);
            if ($res === true) {
                $this->success(__('Login succeeded!'), [
                    'userInfo' => $this->auth->getInfo()
                ]);
            } else {
                $msg = $this->auth->getError();
                $msg = $msg ?: __('Incorrect user name or password!');
                $this->error($msg);
            }
        }

        $this->success('', [
            'captcha' => $captchaSwitch
        ]);
    }

    /**
     * 管理员注销
     * @return void
     */
    public function logout(): void
    {
        if ($this->request->isPost()) {
            $refreshToken = $this->request->post('refreshToken', '');
            if ($refreshToken) Token::delete((string)$refreshToken);
            $this->auth->logout();
            $this->success();
        }
    }

    public function getLoginAdminStores(): void
    {
        $adminStores = Admin::getLoginAdminStores();
        $this->success('', $adminStores);
    }
    /**
     * 迁移数据的方法
     */
    public function migration(): void
    {
        // 检查门店是否已存在
        $existingStore = \think\facade\Db::name('store')->where('name', '南京店')->find();
        if ($existingStore) {
            $this->success('门店已存在，无需重复创建', [
                'store_id' => $existingStore['id'],
                'store_name' => $existingStore['name'],
                'message' => '南京店已存在于系统中'
            ]);
        }
        try {
            // 开启事务
            \think\facade\Db::startTrans();

            // 准备还原SQL语句数组
            $rollbackSql = [];
            $rollbackSql[] = "-- 数据迁移还原SQL - 生成时间: " . date('Y-m-d H:i:s');
            $rollbackSql[] = "-- 注意：请按照从下往上的顺序执行以下SQL语句";
            $rollbackSql[] = "";

            // 1. 创建南京店门店记录
            $storeData = [
                'name' => '南京店',
                'status' => 1, // 营业中
                'province_id' => 0,
                'city_id' => 0,
                'district_id' => 0,
                'address' => '南京市',
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s')
            ];

            $storeId = \think\facade\Db::name('store')->insertGetId($storeData);

            if (!$storeId) {
                throw new \Exception('创建门店失败');
            }

            // 记录删除门店的还原SQL
            $rollbackSql[] = "-- 5. 删除创建的门店记录";
            $rollbackSql[] = "DELETE FROM store WHERE id = {$storeId};";
            $rollbackSql[] = "";

            // 2. 建立管理员与门店的关联关系 - 将所有现有管理员关联到新门店
            $adminIds = \think\facade\Db::name('admin')->column('id');
            $adminStoreRelations = [];
            foreach ($adminIds as $adminId) {
                $adminStoreRelations[] = [
                    'admin_id' => $adminId,
                    'store_id' => $storeId
                ];
            }

            if (!empty($adminStoreRelations)) {
                \think\facade\Db::name('admin_store_relation')->insertAll($adminStoreRelations);

                // 记录删除管理员门店关联的还原SQL
                $rollbackSql[] = "-- 4. 删除管理员与门店的关联关系";
                $rollbackSql[] = "DELETE FROM admin_store_relation WHERE store_id = {$storeId};";
                $rollbackSql[] = "";
            }

            // 3. 更新appointment表的store_id字段 - 将所有现有预约关联到新门店
            $appointmentIds = \think\facade\Db::name('appointment')->where('store_id', 0)->column('id');
            if (!empty($appointmentIds)) {
                \think\facade\Db::name('appointment')
                    ->where('store_id', 0)
                    ->update(['store_id' => $storeId]);

                // 记录还原预约store_id的SQL
                $rollbackSql[] = "-- 3. 还原预约表的store_id字段";
                $appointmentIdsStr = implode(',', $appointmentIds);
                $rollbackSql[] = "UPDATE appointment SET store_id = 0 WHERE id IN ({$appointmentIdsStr});";
                $rollbackSql[] = "";
            }

            // 4. 建立门店与医务人员的关联关系 - 将所有现有医务人员关联到新门店
            $medicalStaffIds = \think\facade\Db::name('medical_staff')->column('id');
            $storeMedicalStaffRelations = [];
            foreach ($medicalStaffIds as $medicalStaffId) {
                $storeMedicalStaffRelations[] = [
                    'store_id' => $storeId,
                    'medical_staff_id' => $medicalStaffId
                ];
            }

            if (!empty($storeMedicalStaffRelations)) {
                \think\facade\Db::name('store_medical_staff_relation')->insertAll($storeMedicalStaffRelations);

                // 记录删除门店医务人员关联的还原SQL
                $rollbackSql[] = "-- 2. 删除门店与医务人员的关联关系";
                $rollbackSql[] = "DELETE FROM store_medical_staff_relation WHERE store_id = {$storeId};";
                $rollbackSql[] = "";
            }

            // 5. 更新room表的store_id字段 - 将所有现有房间关联到新门店
            $roomIds = \think\facade\Db::name('room')->where('store_id', 0)->column('id');
            if (!empty($roomIds)) {
                \think\facade\Db::name('room')
                    ->where('store_id', 0)
                    ->update(['store_id' => $storeId]);

                // 记录还原房间store_id的SQL
                $rollbackSql[] = "-- 1. 还原房间表的store_id字段";
                $roomIdsStr = implode(',', $roomIds);
                $rollbackSql[] = "UPDATE room SET store_id = 0 WHERE id IN ({$roomIdsStr});";
                $rollbackSql[] = "";
            }

            // 生成还原SQL文件
            $rollbackSqlContent = implode("\n", $rollbackSql);
            $rollbackFileName = 'rollback_migration_' . date('Y_m_d_H_i_s') . '.sql';
            $rollbackFilePath = root_path() . 'sql' . DIRECTORY_SEPARATOR . $rollbackFileName;

            // 确保sql目录存在
            $sqlDir = root_path() . 'sql';
            if (!is_dir($sqlDir)) {
                mkdir($sqlDir, 0755, true);
            }

            file_put_contents($rollbackFilePath, $rollbackSqlContent);
            // 提交事务
            \think\facade\Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            \think\facade\Db::rollback();
            $this->error('数据迁移失败: ' . $e->getMessage());
        }
        $this->success('数据迁移成功', [
            'store_id' => $storeId,
            'store_name' => '南京店',
            'admin_count' => count($adminIds),
            'medical_staff_count' => count($medicalStaffIds),
            'updated_appointments' => count($appointmentIds ?? []),
            'updated_rooms' => count($roomIds ?? []),
            'rollback_file' => $rollbackFileName,
            'rollback_path' => $rollbackFilePath
        ]);
    }
}
